<?php


namespace App\Services;


use App\Models\FootagePart;
use App\Models\Footage;
use App\Models\Video;
use App\Services\FootageService;
use App\Utils\Code;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class PartService extends BaseService
{
    /**
     * 创建数据
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function store(array $params) {
        if (!$this->checkParams($params)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($params){
            $model = new FootagePart();
            $footage = (new FootageService)->show($params['footage_id']);
            $model->footage_id = $params['footage_id'];
            $model->audio_id = $footage->audio_id;
            $model->index = $params['index'];
            if (isset($params['name']) && $params['name']){
                if (FootagePart::where('footage_id', $params['footage_id'])->where('name', $params['name'])->first()) {
                    throw new \Exception('名称已经存在', Code::EXIST_REPEAT);
                }
                $model->name = $params['name'];
            }
            if (isset($params['audio_ss']) && is_numeric($params['audio_ss'])){
                $model->audio_ss = $params['audio_ss'];
            }
            if (isset($params['audio_t']) && is_numeric($params['audio_t'])){
                $model->audio_t = $params['audio_t'];
            }
            if (isset($params['video_id']) && is_numeric($params['video_id'])){
                $model->video_id = (int)$params['video_id'];
                if ($model->footage->status == 2) {
                    $this->incrementVideoUseCount($model->video_id);
                }
            }
            if (isset($params['video_ss']) && is_numeric($params['video_ss'])){
                $model->video_ss = $params['video_ss'];
            }
            $model->save();
            return $this->show($model->id);
        });
    }

    /**
     * 数据信息
     * @param $id
     * @param bool $simple
     * @param bool $abnormal
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function show($id, $abnormal = true) {
        $model = FootagePart::where('id', $id)->with(['audio'])->first();
        if (!$model && $abnormal){
            throw new \Exception('不存在的ID', Code::EMPTY_DATA);
        }
        return $model;
    }

    /**
     * 更新数据
     * @param $id
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function update($id, array $params) {
        if (!$this->checkParams($params, true)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($id, $params){
            $model = $this->show($id);
            if (isset($params['name']) && $params['name']){
                if (FootagePart::where('footage_id', $model->footage_id)->where('name', $params['name'])
                    ->where('id', '<>', $id)->first()) {
                    throw new \Exception('名称已经存在', Code::EXIST_REPEAT);
                }
                $model->name = $params['name'];
            }
            if (isset($params['audio_t']) && is_numeric($params['audio_t'])){
                $model->audio_t = $params['audio_t'];
            }
            if (isset($params['video_id']) && is_numeric($params['video_id'])){
                if ($model->footage->status == 2) {
                    if (!$model->video_id) {
                        $this->incrementVideoUseCount($params['video_id']);
                    } elseif ($model->video_id && $model->video_id != $params['video_id']) {
                        $this->decrementVideoUseCount($model->video_id);
                        $this->incrementVideoUseCount($params['video_id']);
                    }
                }
                $model->video_id = (int)$params['video_id'];
            }
            if (isset($params['video_ss']) && is_numeric($params['video_ss'])){
                $model->video_ss = $params['video_ss'];
            }
            if (isset($params['path']) && $params['path']){
                $model->path = $params['path'];
            }
            $model->save();
            return $this->show($id);
        });
    }

    /**
     * 删除数据
     * @param $id
     * @return mixed
     * @throws \Exception
     */
    public function destroy(array $ids = []) {
        if (!$this::$admin) {
            throw new \Exception('你没有权限进行删除', Code::LACK_OF_CONDITIONS);
        }
        return DB::transaction(function () use ($ids) {
            foreach ($ids as $id) {
                $model = FootagePart::find($id);
                if ($model->footage->status == 2) {
                    $this->decrementVideoUseCount($model->video_id);
                }
            }
            return FootagePart::whereIn('id', $ids)->delete();
        });
    }

    /**
     * 数据分页
     * @param array $params
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function lists(array $params = []) {
        if (isset($params['mode']) && $params['mode'] == 'select') {
            $model = FootagePart::select(['id', 'name', 'video_id']);
        } else {
            $model = FootagePart::with(['video', 'audio']);
        }
        if (isset($params['audio_id']) && $params['audio_id']) {
            $model = $model->where('audio_id', '=', $params['audio_id']);
        }
        if (isset($params['footage_id']) && $params['footage_id']) {
            $model = $model->where('footage_id', '=', $params['footage_id']);
        }
        $lists = $model->orderBy('index', 'asc')->orderBy('id', 'asc')->get();
        return $lists;
    }

    /**
     * 验证参数
     * @param array $params
     * @param bool $isUpdate
     * @return array
     * @throws \Exception
     */
    private function checkParams(array $params, $isUpdate = false){
        $rules = [
            'footage_id' => ['bail', 'required', 'integer'],
            'audio_ss' => ['bail', 'nullable', 'numeric'],
            'audio_t' => ['bail', 'nullable', 'numeric'],
            'index' => ['bail', 'required', 'numeric'],
            'name' => ['bail', 'nullable', 'string', 'between:1,50'],
            'video_id' => ['bail', 'nullable', 'integer'],
            'video_ss' => ['bail', 'nullable', 'numeric'],
            'path' => ['bail', 'nullable', 'string']
        ];
        if ($isUpdate){
            // 删除必选条件
            foreach ($rules as $field => &$rule){
                if (isset($rule[1]) && $rule[1] == 'required') {
                    unset($rule[1]);
                }
            }
        }
        $validator = Validator::make($params, $rules, [], [
            'footage_id' => '镜头组ID',
            'audio_ss' => '音频起始秒数',
            'audio_t' => '音频持续秒数',
            'index' => '索引',
            'name' => '名称',
            'video_id' => '视频ID',
            'video_ss' => '视频起始秒数',
            'path' => '预览视频路径'
        ]);
        if ($validator->fails()) {
            throw new \Exception($validator->errors()->first(), Code::PARAMETER_ERROR);
        }
        return $params;
    }

    /**
     * 切分镜头
     */
    public function clip($id, array $params) {
        if (!$this->checkClipParams($params, true)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($id, $params){
            $model = $this->show($id);
            $mid_ss = (double)$params['mid_ss'];
            $audio_t_1 = $mid_ss - $model->audio_ss;
            $audio_t_2 = $model->audio_t - $audio_t_1;
            $model->audio_t = $audio_t_1;
            $footage = Footage::find($model->footage_id);
            foreach($footage->parts as $part) {
                if ($part->index > $model->index) {
                    $part->index += 1;
                    $part->save();
                }
            }
            $newModal = $this->store([
                'footage_id' => $model->footage_id,
                'audio_ss' => $mid_ss,
                'audio_t' => $audio_t_2,
                'index' => $model->index + 1
            ]);
            $model->path = '';
            $model->save();
            if ($footage->status == 2) {
                $this->decrementVideoUseCount($model->video_id);
            }
            return $newModal;
        });
    }

    /**
     * 验证参数
     */
    private function checkClipParams(array $params){
        $rules = [
            'mid_ss' => ['bail', 'required', 'numeric']
        ];
        $validator = Validator::make($params, $rules, [], [
            'mid_ss' => '切分秒数'
        ]);
        if ($validator->fails()) {
            throw new \Exception($validator->errors()->first(), Code::PARAMETER_ERROR);
        }
        return $params;
    }
    
    /**
     * 切分镜头
     */
    public function merge($id, array $params) {
        if (!$this->checkMergeParams($params, true)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($id, $params){
            $mergeModel = $this->show($params['merge_id']);
            $model = $this->show($id);
            $mergeModel->audio_t = $mergeModel->audio_t + $model->audio_t;
            $mergeModel->path = '';
            $mergeModel->save();
            $footage = Footage::find($model->footage_id);
            foreach($footage->parts as $part) {
                if ($part->index > $model->index) {
                    $part->index -= 1;
                    $part->save();
                }
            }
            if ($footage->status == 2) {
                $this->decrementVideoUseCount($mergeModel->video_id);
                $this->decrementVideoUseCount($model->video_id);
            }
            $model->delete();
            return true;
        });
    }

    /**
     * 验证参数
     */
    private function checkMergeParams(array $params){
        $rules = [
            'merge_id' => ['bail', 'required', 'numeric']
        ];
        $validator = Validator::make($params, $rules, [], [
            'merge_id' => '合并入的镜头ID'
        ]);
        if ($validator->fails()) {
            throw new \Exception($validator->errors()->first(), Code::PARAMETER_ERROR);
        }
        return $params;
    }

    private function incrementVideoUseCount($videoId) {
        if ($videoId == 0 || !$videoId) return;
        $video = Video::find($videoId);
        if ($video) {
            $video->use_count += 1;
            $video->save();
        }
    }

    private function decrementVideoUseCount($videoId) {
        if ($videoId == 0 || !$videoId) return;
        $video = Video::find($videoId);
        if ($video) {
            $video->use_count = $video->use_count - 1 >= 0 ? $video->use_count - 1 : 0;
            $video->save();
        }
    }
}
